Skip to content

Conversation

nefrob
Copy link

@nefrob nefrob commented Jul 20, 2025

Description

Resolves: #9707.

  • Apply unique together constraint validation to unique constraint with a single constraint field if there are other fields used in the constraint conditions

for unique_together in parent_class._meta.unique_together:
yield unique_together, model._default_manager, [], None
for constraint in parent_class._meta.constraints:
if isinstance(constraint, models.UniqueConstraint) and len(constraint.fields) > 1:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do this need to be removed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're now including the condition fields as part of the applicable fields that contribute to this count below. If we kept this here the condition fields would not be considered, which we need for this fix.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be a distinction made between condition fields and constraint fields here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could split out the logic for clarity to require >1 constraint fields or 1 constraint field and 1+ condition fields distinct from the constraint field. Practically that would be the same however.

If you want to split our unique together constraints with a single constraint field and distinct condition fields into a new method, that would require a larger refactor of the existing constraint validation code.

@auvipy auvipy requested a review from Copilot October 16, 2025 07:29
@auvipy auvipy added this to the 3.17 milestone Oct 16, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR updates DRF’s validation to correctly treat single-field UniqueConstraint entries with additional condition fields as unique-together validations rather than per-field UniqueValidators.

  • Extend unique-together detection to include UniqueConstraint with one field when the condition references other fields.
  • Adjust field-level UniqueValidator generation to only apply when no additional condition fields are referenced.
  • Add tests covering condition-based unique-together behavior.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
tests/test_validators.py Adds a model, serializer, and tests for condition-based unique-together validation; updates expectations for single-field UniqueConstraint behavior.
rest_framework/utils/field_mapping.py Imports helper and changes logic to only create UniqueValidator when the union of fields and condition fields is a single field.
rest_framework/serializers.py Updates unique-together constraint discovery to include single-field UniqueConstraints when conditions reference additional fields.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +311 to +314
ConditionUniquenessTogetherModel.objects.create(race_name='example', position=1)

data = {'race_name': 'example', 'position': 0}
serializer = ConditionUniquenessTogetherSerializer(self.instance, data=data)
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The serializer under test is passed an instance of UniquenessTogetherModel (self.instance) instead of ConditionUniquenessTogetherModel. This will cause the update validation to target the wrong model. Capture and pass the instance of ConditionUniquenessTogetherModel created in this test.

Suggested change
ConditionUniquenessTogetherModel.objects.create(race_name='example', position=1)
data = {'race_name': 'example', 'position': 0}
serializer = ConditionUniquenessTogetherSerializer(self.instance, data=data)
instance = ConditionUniquenessTogetherModel.objects.create(race_name='example', position=1)
data = {'race_name': 'example', 'position': 0}
serializer = ConditionUniquenessTogetherSerializer(instance, data=data)

Copilot uses AI. Check for mistakes.

Comment on lines +251 to +252
Failing unique together validation should result in non field errors when a condition-based
unique together constraint is violated.
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hyphenate 'non-field errors' for correctness and consistency with DRF terminology.

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serializer UniqueConstraint validation fails incorrectly on create with conditional fields

3 participants